package com.c5p1ng.distributed.lock.core;

import com.c5p1ng.distributed.lock.config.LockConfig;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 可重入锁
 */
public class ReentrantLock implements ILock {
    private RLock rLock;
    private RedissonClient redissonClient;
    private LockConfig lockConfig;

    public ReentrantLock(RedissonClient redissonClient, LockConfig lockConfig) {
        this.redissonClient = redissonClient;
        this.lockConfig = lockConfig;
    }


    @Override
    public boolean tryAcquire(String lockKey, long acquireTimeout, long expireTime) {
        try {
            rLock = redissonClient.getLock(lockConfig.getKeyPrefix() + lockKey);
            return rLock.tryLock(lockConfig.getAcquireTimeout(), lockConfig.getExpireTime(), TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            return false;
        }
    }

    @Override
    public boolean acquire(String lockKey) {
        return tryAcquire(lockConfig.getKeyPrefix() + lockKey, lockConfig.getAcquireTimeout(), lockConfig.getExpireTime());
    }

    @Override
    public boolean release() {
        if(rLock.isHeldByCurrentThread()) {
            try {
                return rLock.forceUnlockAsync().get();
            } catch (InterruptedException | ExecutionException e) {
                return false;
            }
        }
        return false;
    }
}
